#!/usr/bin/env python3

# Copyright (c) 2020-2021 Fpemud <fpemud@sina.com>
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.


import subprocess
from .._util import WinFile
from .._const import Arch


class TxtSetupOemFile(WinFile):

    # txtsetup.oem follows the Microsoft format rules for an INF file, but with only five sections.
    #
    # [Disks]
    # disk = "description",tagfile,directory
    #
    # This section describes the installation disks. This is a required section. There can be multiple disk = lines, but most txtsetup.oem files only have one disk. The parameters are below.
    #     disk        - This is a tag used to identify a particular disk
    #     description - String is used to prompt the user for the disk.
    #     tagfile     - Path to a file on the disk used to verify the correct disk is in the drive.
    #                   This can be any file on the disk.
    #                   Good practice is to make this a separate file that contains a description of the installation.
    #     directory   - Path to the directory where the files are located. For a floppy based installation this may be anything, but for an automated install this directory must
    #                   be backslash ("\"), except for automated installations from FAT32 where this must be a period (".")
    #
    # [Defaults]
    # SCSI = ID
    #
    # This section is optional and describes the default installation. If this section is not present, the first entry in the [SCSI] section described below will be the default.
    # Note that even though this identifies the default driver for the [SCSI] section, the driver does not need to be for a SCSI device. The parameters are:
    #     ID - Tag for the componen
    #
    # [SCSI]
    # ID = "description"
    #
    # This section provides the description of a driver used to prompt the user. This is a required section. These drivers do not need to be for a SCSI device. The [SCSI] section
    # name is a legacy from previous versions of Windows that supported txtsetup.oem installation of display, keyboard, mouse, CD-ROM, as well as SCSI and Computer (HAL and ntdetect).
    # There can be multiple entries in this section; all the descriptions will be displayed for the user. The parameters are:
    #     ID - Tag for the component description String is used to prompt the user for the device installation.
    #          Make this a useful description, since this appears as the prompt for the user.
    #          Additionally, this string is used in automated installations to identify the driver to install.
    #
    # [Files.SCSI.ID]
    # driver = disk, filename, service
    # inf = disk, filename
    # catalog = disk, filename
    #
    # This section describes the files to copy as part of the installation. This is a required section. There can be multiple entries for each line type (driver, inf and catalog).
    # Note I do not describe installing a DLL file since it is not valid for SCSI with automated installations. Attempts have been made to install more than one driver and INF for
    # a given ID, however, this does not work for an automated install, and is problematic for regular floppy installation. The parameters are:
    #     ID       - Tag for the component
    #     disk     - This is a tag used to identify a particular disk
    #     filename - Name of the file to load
    #     service  - Name of registry key in the HKLM\CurrentControlSet\Services to create
    #
    # [Config. service]
    # value = subkeyname,valuename,valuetype,value
    #
    # This section describes the registry entries to create as part of the installation. This section is optional. There can be multiple value lines in the section. The parameters are:
    #     service    - Name of service, same as the entry from the driver line from above
    #     subkeyname - Name of registry key under Service to place the value
    #     valuename  - Name of registry value
    #     valuetype  - One of REG_DWORD, REG_SZ, REG_EXPAND_SZ, REG_BINARY or REG_MULTI_SZ
    #     value      - The value of the key
    #
    # [HardwareIDs.SCSI.service]
    # id = "deviceID","Service"
    #
    # This section associates plug and play hardware identifiers with a given service and driver. The section is not required for a floppy installation, but is required to do an
    # automated installation of the driver. Multiple id lines are permitted. The parameters are:
    #     service  - Name of service, same as the entry from the driver line from above.
    #     deviceID - A plug and play device ID. This must match a value in the INF file for the device. This ID should be for a hardware device such as PCI or ACPI. If this is a
    #                virtual device ID not rooted in hardware, the driver will be loaded, then a short time later unloaded when it was determined that the reference count of the
    #                driver object was zero. This ID can be a software enumerated ID if this is a load of a filter driver or an NT4.0 style driver, where other mechanisms connect
    #                the driver into the device space.

    def __init__(self, ts):
        self._ts = ts

    def get_filepath(self):
        return "TXTSETUP.OEM"

    def get_content(self):
        buf = ""

        if self._ts.arch == Arch.X86:
            buf += "[Disks]\n"
            buf += 'd1 = "OEM DISK (SCSI) WinXP/32-bit",\\disk1,\\i386\n'
            buf += "\n"
            buf += "[Defaults]\n"
            buf += "SCSI = WXP32\n"
            buf += "\n"
            buf += "[scsi]\n"
            buf += 'WXP32 = "Red Hat VirtIO BLOCK Disk Device WinXP/32-bit"\n'
            buf += "\n"
            buf += "[Files.scsi.WXP32]\n"
            buf += "driver  = d1, viostor.sys, viostor\n"
            buf += "inf     = d1, viostor.inf\n"
            buf += "catalog = d1, viostor.cat\n"
            buf += "\n"
            buf += "[HardwareIds.scsi.WXP32]\n"
            buf += 'id = "PCI\\VEN_1AF4&DEV_1001&SUBSYS_00021AF4&REV_00", "viostor"\n'
            buf += "\n"
        elif self._ts.arch == Arch.X86_64:
            # currently, only win2003 has 64bit viostor driver
            assert False
        else:
            assert False

        return buf


class SetupDriverFloppyImageFile:

    # setup driver floppy should contain the following files:
    # 1. The standard driver, INF and catalog files of a normal installation
    # 2. A txtsetup.oem file to direct the text-mode setup installation
    # 3. A tag file to identify the disk. This can be one of the files listed in (1) above or a separate file. I normally use a separate file that contains a product description and copyright notice

    @staticmethod
    def create(ts, floppy_filepath, tmp_filepath):
        # FIXME: fusefat converts filenames to "~1", so windows xp can't recognize it, we have to use mcopy
        subprocess.check_call(["mformat", "-i", floppy_filepath, "-f", "1440", "-C"])

        # create txtsetup.oem file
        txtSetupOemFile = TxtSetupOemFile(ts)
        with open(tmp_filepath, "wb") as f:
            f.write(txtSetupOemFile.get_binary_content())
        subprocess.check_call(["mcopy", "-i", floppy_filepath, tmp_filepath, "::" + txtSetupOemFile.get_filepath()])

        # create tag file
        with open(tmp_filepath, "w") as f:
            f.write("")
        subprocess.check_call(["mcopy", "-i", floppy_filepath, tmp_filepath, "::DISK1"])

        # copy driver files
        pass
        # with IsoMount(srcMedia.get_virtio_win_iso_filepath(), workDirObj.iso_op_dirpath):
        #     subprocess.check_call(["mcopy", "-s", "-i", floppy_filepath, os.path.join(workDirObj.iso_op_dirpath, "viostor", "xp", "x86"), "::I386"])
